
package com.javazyw.utils.net;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.commons.net.ftp.FTP;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPFile;

import com.javazyw.entity.bo.FtpArgs;

public class FtpUtil11 {

	private static FTPClient ftpClient = null;
	private static Log logger = LogFactory.getLog(FtpUtil11.class);
	public static final int BINARY_FILE_TYPE = FTP.BINARY_FILE_TYPE;
	public static final int ASCII_FILE_TYPE = FTP.ASCII_FILE_TYPE;
	
	public boolean isConnect(){
		return ftpClient.isConnected();
	}
	
	public FtpUtil11() {}
	
	public FtpUtil11(FtpArgs ftpArgs) {
		connectServer(ftpArgs.getHost(),
				ftpArgs.getPort(), ftpArgs.getUser(),
				ftpArgs.getPassword(), ftpArgs.getDir());
	}
	
	public boolean connectServer(String server, int port, String user,
			String password, String path){
		boolean ret = false;
		try {
			ftpClient = new FTPClient();
			ftpClient.connect(server, port);
			System.out.println("Connected to " + server + ".");
			System.out.println(ftpClient.getReplyCode());
			ftpClient.login(user, password);
			ftpClient.enterLocalPassiveMode();
			
			// Path is the sub-path of the FTP path
			if (path != null && path.length() != 0) {
				ftpClient.changeWorkingDirectory(path);
			}
			ret = true;
		} catch (Exception e) {
			e.printStackTrace();
		}
		
		return ret;
		
	}
	
	/**
	 * 连接ftp服务器
	 * 
	 * @param server
	 *            机器名或ip地址
	 * @param port
	 *            端口号
	 */
	public boolean openServer(String hostname, int port) {
		
		boolean ret = false;
		ftpClient = new FTPClient();
		try {
			logger.info("connect to server.........");
			ftpClient.connect(hostname, port);
			
			ret = true;
			logger.info("connect to server.........success");
		} catch (Exception e) {
			logger.info("connect to server.........unsuccessful");
			e.printStackTrace();
		}
		
		return ret;
	}
	
	/**
	 * 连接ftp服务器
	 * 
	 * @param server
	 *            机器名或ip地址
	 */
	public boolean openServer(String hostname) {
			
			boolean ret = false;
			ftpClient = new FTPClient();
			try {
				logger.info("connect to server.........");
				ftpClient.connect(hostname, 21);
				
				ret = true;
				logger.info("connect to server.........success");
			} catch (Exception e) {
				logger.info("connect to server.........unsuccessful");
				e.printStackTrace();
			}
			
			return ret;
		}


	/**
	 * 登录ftp服务器
	 * 
	 * @param user
	 *            用户名
	 * @param password
	 *            密码
	 */
	public boolean login(String user, String password) {
		boolean ret = false;
		try {
			
			int reply = ftpClient.getReplyCode();
			/*if(!FTPReply.isPositiveCompletion(reply)){
				this.ftpClient.disconnect();
				logger.info("is already login.........");
				return ret;
			}*/
			
			logger.info("login to server.........");
			ftpClient.login(user, password);
			System.out.println(ftpClient.getControlEncoding());
		//	ftpClient.setControlEncoding("GBK");
			ret = true;
			logger.info("login to server.........success");
		} catch (Exception ex) {
			ret = false;
			logger.info("login to server.........unsuccessful");
			ex.printStackTrace();
		}
		return ret;
	}
	
	/**
	 * 关闭ftp服务器
	 * 
	 * @return
	 */
	public boolean closeServer() {
		boolean ret;
		try {
			
			logger.info("closeServer to server.........");
			if(ftpClient.isConnected()){
				ftpClient.disconnect();
			}
			ret = true;
		} catch (Exception ex) {
			logger.info("closeServer to server.........unsuccessful");
			ex.printStackTrace();
			ret = false;
		}
		return ret;
	}
	
	
	/**
	 * 设置传输文件的类型
	 * @param fileType
	 */
	public void setFileType(int fileType){
		
		try {
			this.ftpClient.setFileType(fileType);
			logger.info("setFileType  successful.....");
		} catch (IOException e) {
			logger.info("setFileType  unsuccessful.....");
			e.printStackTrace();
		}
	}
	
	/**
	 * 切换目录
	 * 
	 * @param path
	 *            目的目录
	 */
	public boolean cd(String path) {
		boolean ret;
		try {
			logger.info("cd  path .........");
			ftpClient.changeWorkingDirectory(path);
			ret = true;
		} catch (Exception ex) {
			ret = false;
			ex.printStackTrace();
		}
		return ret;
	}
	
	
	/**
	 * 文件重命名
	 * 
	 * @param source
	 *            源文件
	 * @param dest
	 *            目标文件
	 * 
	 */
	public boolean rename(String source, String dest) {
		boolean ret;
		try {
			ftpClient.rename(source, dest);
			logger.info("file rename.....successful");
			ret = true;
		} catch (Exception ex) {
			ex.printStackTrace();
			logger.info("file rename.....successful");
			ret = false;
		}
		return ret;
	}
	
	
	/**
	 * 在远程服务器上创建目录
	 * @param pathName
	 * @return
	 */
	public boolean createDirectory(String pathName){
		boolean ret = false;
		try {
			logger.info("createDirectory .........");
			ret = ftpClient.makeDirectory(pathName);
		} catch (IOException e) {
			e.printStackTrace();
		}
		return ret;
	}
	
	public boolean makeDir(String pathName){
		boolean ret = false;
		try {
			logger.info("makeDir .........");
			ftpClient.mkd(pathName);
			ret = true;
		} catch (IOException e) {
			e.printStackTrace();
		}
		return ret;
		
	}

	/**
	 * 在远程服务器上删除目录
	 * @param pathName
	 * @return
	 */
	public boolean removeDirectory(String pathName){
		boolean ret = false;
		try {
			logger.info("removeDirectory .........");
			ret = ftpClient.removeDirectory(pathName);
		} catch (IOException e) {
			e.printStackTrace();
		}
		return ret;
	}
	
	/**
	 * 这个方法还有问题---无法使用 总抛出异常
	 * @param path
	 * @return
	 * @throws IOException
	 */
	public List<String> getFileList(String path) {
		// listFiles return contains directory and file, it's FTPFile instance
		// listNames() contains directory, so using following to filer directory.
		//String[] fileNameArr = ftpClient.listNames(path);
		List<String> retList = new ArrayList<String>();
		try {
			FTPFile[] ftpFiles= ftpClient.listFiles();
			if (ftpFiles == null || ftpFiles.length == 0) {
				return retList;
			}
			for (FTPFile ftpFile : ftpFiles) {
				if (ftpFile.isFile()) {
					retList.add(ftpFile.getName());
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		
		return retList;
	}

	
	/**
	 * 删除文件
	 * @param pathName 文件名
	 * @return
	 */
	public boolean deleteFile(String pathName){
		boolean ret = false;
		
		try {
			logger.info("delete  file .........");
			return ftpClient.deleteFile(pathName);
		} catch (IOException e) {
			e.printStackTrace();
		}
		return ret;
	}


	/**
	 * 取得当前目录下的所有的文件名字
	 * @return
	 */
	public String[] getFileNames(){
		String[] names = null;
		try {
			names =  ftpClient.listNames();
		} catch (Exception e) {
			// TODO: handle exception
			e.printStackTrace();
		}
		
		return names;
	}
	/**
	 * 取得当前参数目录下的所有的文件名字 
	 * @param path 目录名 test/aaa/ 或者test/aaa
	 * @return
	 */
	public String[] getFileNames(String path){
		String[] names = null;
		try {
			names =  ftpClient.listNames(path);
		} catch (Exception e) {
			e.printStackTrace();
		}
		
		return names;
	}
	
	
	/**
	 * 上传文件
	 * @param fileName  本地文件名
	 * @param newName  远程主机 存储的文件名
	 * @return
	 */
	public boolean uploadFile(String fileName, String newName) {
		boolean ret = false;
		InputStream iStream = null;
		try {
			this.setFileType(BINARY_FILE_TYPE);
			logger.info("uploadFile  .........");
			iStream = new FileInputStream(fileName);
			
			ret = ftpClient.storeFile(newName, iStream);
			logger.info("uploadFile  .........success");
			ret = true;
		} catch (Exception e) {
			ret = false;
			logger.info("uploadFile .........unsuccessful");
			e.printStackTrace();
		} finally {
			if (iStream != null) {
				try {
					iStream.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
		return ret;
	}


	/**
	 * 文件上传--远程服务器的名字与本地同名
	 * @param fileName
	 * @return
	 */
	public boolean uploadFile(String fileName){
		return uploadFile(fileName, fileName);
	}

	
	/**
	 * 上传文件
	 * @param iStream 输入流
	 * @param newName
	 * @return
	 */
	public boolean uploadFile(InputStream iStream, String newName) {
		boolean ret = false;
		try {
			
			ret = ftpClient.storeFile(gbkToISO8859(newName), iStream);
			
			logger.info("uploadFile  by InputStream successful.......");
		} catch (IOException e) {
			ret = false;
			logger.info("uploadFile  by InputStream unsuccessful.......");
			e.printStackTrace();
		} finally {
			if (iStream != null) {
				try {
					iStream.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
		return ret;
	}


	/**
	 * 上传文件--根据文件名和文件内容
	 * 
	 * @param path
	 *            路径+文件名
	 * @param fileContent
	 *            文件内容
	 */
	public boolean upload(String remoteFileName , String fileContent){
		OutputStream os = null;
		boolean ret = false;
		try {
			os = ftpClient.storeFileStream(gbkToISO8859(remoteFileName));
			os.write(fileContent.getBytes());
		} catch (IOException e) {
			ret = false;
			e.printStackTrace();
		} finally{
			if(os != null){
				try {
					os.flush();
					os.close();
					ftpClient.completePendingCommand();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
		return ret;
	}
	
	/**
	 * 文件下载
	 * @param remoteFileName
	 * @param localFileName
	 * @return
	 * @throws IOException
	 */
	public boolean download(String remoteFileName, String localFileName) {
		boolean ret = false;
		File outfile = new File(localFileName);
		OutputStream oStream = null;
		this.setFileType(FTPClient.BINARY_FILE_TYPE);
		try {
			logger.info("downloadFile  .........");
			oStream = new FileOutputStream(outfile);
			ret = ftpClient.retrieveFile(gbkToISO8859(remoteFileName), oStream);
			
			logger.info("downloadFile  .........success");
			ret = true;
		} catch (Exception e) {
			ret = false;
			logger.info("downloadFile  .........unsuccessful");
			e.printStackTrace();
		} finally {
			try {
				oStream.flush();
				oStream.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return ret;
	}

	/**
	 * 下载文件
	 * 返回文件内容
	 * @param remoteFileName
	 *            路径+文件名
	 * @return
	 */
	public String download(String remoteFileName){
		InputStream is;
		BufferedReader in = null;
		String buffer = "";
		String line = "";
		try {
			is = ftpClient.retrieveFileStream(gbkToISO8859(remoteFileName));
			in = new BufferedReader(new InputStreamReader(is));
			while ((line = in.readLine()) != null) {
				buffer += line + "\r\n";
			}
		} catch (IOException e) {
			e.printStackTrace();
		}finally {
			if (in != null) {
				try {
					in.close();
					ftpClient.completePendingCommand();
				} catch (Exception ex) {
					ex.printStackTrace();
				}
			}
		}
		return buffer;
	}

	/**
	 * 切换到父目录
	 */
	public void toParentDir(){
		try {
			
			ftpClient.changeToParentDirectory();
			logger.info("go to parent dir.....");
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	/**
	  * 转码[GBK ->  ISO-8859-1]
	  *不同的平台需要不同的转码
	  * @param obj
	  * @return
	  */
	private  String gbkToISO8859(Object obj) {
	  try {
	   if (obj == null)
	    return "";
	   else
	    return obj.toString();//  new String(obj.toString().getBytes("GBK"), "iso-8859-1");
	  } catch (Exception e) {
	   return "";
	  }
	}

	/**
	 * 取当前目录下的所有目录(不包括子目录)
	 * @return dirc 当前目录名称
	 * */
	public String[] getDirectory(){
		String[] dirc = null;
		try {
			FTPFile[] files = ftpClient.listFiles();
			if(null != files && files.length != 0 ){
				int dricLength = 0;
				for(Object object:files){
					FTPFile f = (FTPFile)object;
					if(f.isDirectory()){
						dricLength++;
					}
				}
				dirc = new String[dricLength];
				for(int i=0;i<files.length;i++){
					if(files[i].isDirectory()){
						dirc[i] = files[i].getName(); 
					}					
				}
			}
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return dirc;
	}
	
	
	
	/**
	 * @param args
	 */
	public static void main(String[] args)throws Exception {
		
		//http://www.linuxidc.com/Linux/2014-10/107585.htm 
		//中文乱码问题 , 本工具类中暂不做处理，因为理论上是不允许有中文的,经测试依然乱码
		
		FtpUtil11 ftp = new FtpUtil11();
		
		boolean b = ftp.connectServer("182.92.84.122", 21, "uftp", "uftp1234321", "ftp");
		System.out.println(b);
		
		//ftp.createDirectory("abc");
		ftp.uploadFile("K:\\1111.jpg", "1.jpg");
		
		if (true) {
			return;
		}
		
		ftp.openServer("127.0.0.1", 21);
		ftp.login("gavinage", "999");
		
		//ftp.uploadFile("J:\\吉林\\cxf\\cccccc.txt", "xiesh.txt");
		
		ftp.download("xiesh.txt", "J:\\吉林\\cxf\\xiesh.txt");
		ftp.closeServer();
		if(true)
			return;
		//ftp.createDirectory("test");
		//ftp.cd("/test");
		//List lsf = ftp.getFileList("/test/");
		//System.out.println(lsf.size());
		String[] ss = ftpClient.listNames("test/aaa/"); 
		for (int i = 0; i < ss.length; i++) {
			System.out.println(ss[i]);
		}
		//ftp.deleteFile("test/aaa/"+ss[0]);
		System.out.println("-----------------------------------------");
		/*ss = ftpClient.listNames("test/aaa/"); 
		for (int i = 0; i < ss.length; i++) {
			System.out.println(ss[i]);
		}*/
		FTPFile[] fs  = ftpClient.listFiles(); ///该方法问题滴大大的有--加入jakarta-oro-2.0.8.jar包
		
		for (int i = 0; i < fs.length; i++) {
			FTPFile f = fs[i];
			System.out.println(f.getName() + "====>"+f.getRawListing()+"===>"+f.getType());
		}
		ftp.cd("love");
		System.out.println(ftpClient);
		System.out.println();
		ftp.closeServer();
		if(true)
		return;
		
		System.out.println(ftpClient.getControlEncoding());
		//ftp.uploadFile("J:/harvest/1.txt",ftp.gbkToISO8859("嘿嘿.txt"));  
		///上传跟下载时候如果涉及到的主机文件名是中文的话有问题  上传的时候不能生成中文文件  下载的时候可以生成中文文件 但是文件内部没有内容
		
//		ftp.download(ftp.gbkToISO8859("test/哈哈.txt"), "J:/harvest/11111.txt");
		//System.out.println(ftp.download("test/哈哈.txt"));
		
		
		String xml = "<?xml version=\"1.0\" encoding=\"GBK\"?><Root>" +
				"<Record>" +
		"<OrigDomain>1111</OrigDomain> <HomeDomain>2222</HomeDomain>" +
		"<MsgType>1</MsgType><BIPCode>55555</BIPCode>" +
		"<BIPVer>1000</BIPVer>" +
		"<ProcID>100000000</ProcID><ProcessTime>20110412111111</ProcessTime>" +
		"<Response><RspType>9</RspType> <RspCode>DONE</RspCode><RspDesc>应答测试</RspDesc></Response>" +
		"<TestFlag>1</TestFlag><SvcCont></SvcCont>" +
		"</Record>" +
		"<Record>" +
		"<OrigDomain>1111</OrigDomain> <HomeDomain>2222</HomeDomain>" +
		"<MsgType>1</MsgType><BIPCode>55555</BIPCode>" +
		"<BIPVer>1000</BIPVer>" +
		"<ProcID>100000001</ProcID><ProcessTime>20110412111111</ProcessTime>" +
		"<Response><RspType>9</RspType> <RspCode>DONE</RspCode><RspDesc>应答测试</RspDesc></Response>" +
		"<TestFlag>0</TestFlag><SvcCont></SvcCont>" +
		"</Record>" +
		"</Root>";
		
		ftp.cd("ftp");
		//ftp.upload("GPRSAPN/info_bak/E_apntest88.xml", xml);
		
		ftp.download("GPRSAPN/info_bak/E_apntest88.xml","J:/harvest/houhou.xml");
		
		//ftp.setClose();
		//ftp.openServer("127.0.0.1");
	//	ftp.login("gavinage", "999");
		//ftp.closeServer();
		//ftp.openServer("127.0.0.1");
		//ftp.login("gavinage", "999");
		//ftp.cd("ftp");
		ftp.upload("GPRSAPN/info_bak/E_apntest99.xml", xml);
		String[] aaa = ftp.getFileNames("GPRSAPN/info");
		System.out.println(aaa);
		System.out.println(ftp.isConnect());
		ftp.closeServer();
		System.out.println(ftp.isConnect());
	}
}
